import inspect
import types

# from _hellchin_webrun.src.core.engine.action_step import ActionStep


def dynamic_import_class(class_name_str: str):
    """
    动态导入模块并获取类

    Args:
        class_name_str (str): 包含模块路径和类名的字符串
    """
    module_path, class_name = class_name_str.rsplit('.', 1)
    from importlib import import_module
    module = import_module(module_path)
    return getattr(module, class_name)


class KeyWordManage:
    _FUNC_ALIAS_MAP = {}  # 函数别名注册表
    _ALL_ALIAS_MAP = {}  # 全局别名注册表

    # 动作类，默认继承自ActionStep
    action_class = "_hellchin_webrun.src.core.engine.action_step.ActionStep"    # 字符串避免循环导入

    @staticmethod
    def chinese_alias(*names: str):
        """
        装饰器，用于为函数添加中文别名

        1. 同时支持类方法和普通函数
        2. 支持多中文别名

        Args:
            names (str): 中文别名, 可以有多个
        """

        def decorator(func):
            # 判断方法是否有_chinese_aliases属性
            if not hasattr(func, '_chinese_aliases'):
                func._chinese_aliases = names

            # 返回装饰器函数
            return func

        return decorator

    @staticmethod
    def chinese_alias_of_function(*names: str):
        """
        装饰器，用于为函数添加中文别名
        """

        def decorator(func):
            for name in names:
                if name not in KeyWordManage._ALL_ALIAS_MAP:
                    # print(f"普通函数加入中文别名:{name}")
                    KeyWordManage._FUNC_ALIAS_MAP[name] = func
                    KeyWordManage._ALL_ALIAS_MAP[name] = func
            # 返回装饰器函数
            return func

        return decorator



    # @staticmethod
    @classmethod
    def register_keyword(cls, key, func):
        """
        动态注册关键字

        为平台代码提供注册功能，使其可以使用自定义方法

        Args:
        """
        maps = {}
        exec(func, maps)
        for k, v in maps.items():
            # 判断v是否为函数
            if inspect.isfunction(v):
                # 注册关键字到映射表maps中
                KeyWordManage._FUNC_ALIAS_MAP[key] = v
                # 将关键字添加到ActionStep类中
                # 如果action_class是字符串，则从模块中导入类，否则直接使用类本身
                if isinstance(cls.action_class, str):
                    action_class = dynamic_import_class(cls.action_class)
                    setattr(action_class, k, v)
                # 如果action_class不是字符串，则直接使用类本身
                else:
                    setattr(cls.action_class, k, v)

    @classmethod
    def get_keyword_maps(cls, keyword):
        """
        获取关键字对应的映射表
        """
        return cls._ALL_ALIAS_MAP.get(keyword, None)

    @classmethod
    def get_all_maps(cls):
        """
        获取所有别名映射表
        """
        return cls._ALL_ALIAS_MAP


class ChineseAliasMeta(type):
    """
    自定义的元类，用于在创建类的过程中添加中文别名

    1.自动完成别名注册，无需手动调用add_chinese_aliases
    2.继承体系下所有子类自动获得该能力
    """

    def __call__(self, *args, **kwargs):
        """
        创建新的类实例

        不使用new是因为多继承时，会导致重复调用new方法，导致反复覆盖，影响效率
        """

        # 创建新的类实例, klass 是创建的类实例, 例如：<class '__main__.MyClass'>
        instance = super().__call__(*args, **kwargs)

        # 遍历实例的属性，查找具有 _chinese_aliases 属性的方法，并将别名添加到实例
        for attr_name in dir(instance):  # dir(klass) 返回类的所有属性，例如：['__init__', 'add_chinese_aliases', 'chinese_alias']
            method = getattr(instance, attr_name)  # 获取属性
            if callable(method) and hasattr(method, '_chinese_aliases'):  # 判断方法是否可调用且具有chinese_name属性
                for alias in method._chinese_aliases:
                    # 将方法添加到类属性中
                    setattr(instance, alias, method)
                    KeyWordManage._ALL_ALIAS_MAP[alias] = method

        for name, func in KeyWordManage._FUNC_ALIAS_MAP.items():
            #  如果方法不是类方法
            # print("映射表", KeyWordManage._GLOBAL_ALIAS_MAP)
            # print(f"动态设置中文别名: {name}")
            if inspect.isfunction(func) and not inspect.ismethod(func):
                # 对于普通函数，使用静态方法包装
                setattr(instance, name, staticmethod(func))
            else:
                setattr(instance, name, func)

        #  返回类实例
        return instance


@KeyWordManage.chinese_alias_of_function("加法1")
def add1(a, b):
    return a + b


# 使用示例2
# @add_chinese_aliases
class Calculator2(metaclass=ChineseAliasMeta):
    @KeyWordManage.chinese_alias("加法")
    def add(self, a, b):
        return a + b + 1


class Calculator21(Calculator2):
    @KeyWordManage.chinese_alias("减法")
    def sub(self, a, b):
        return a - b


if __name__ == '__main__':
    # 测试
    calc = Calculator21()
    print(calc.加法1(2, 3))  # 调用不存在的方法，但是被关键字注册了。
    print(calc.add(2, 3))  # 输出: 5
    print(calc.加法(2, 3))  # 输出: 5（通过中文别名调用）
    print(calc.sub(2, 3))  # 输出: -1
    print(calc.减法(2, 3))  # 输出: -1（通过中文别名调用）

    print(KeyWordManage.get_maps())
